package com.maxsalad.common.util;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * Created by 2014-400 on 2016-01-27.
 */
public class DateUtil {
    public static final String YYYYMMDD = "yyyy-MM-dd";
    public static final String YYYYMMDDHMS = "yyyy-MM-dd HH:mm:ss";


    /**
     * 获得当前时间
     *
     * @return
     */
    public static String getNowDateTime() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDDHMS);
        LocalDateTime localDateTime = LocalDateTime.now();

        return localDateTime.format(formatter);
    }

    /**
     * 获得当前时间
     *
     * @param format 返回格式,例如:yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String getNowDateTime(String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        LocalDateTime localDateTime = LocalDateTime.now();

        return localDateTime.format(formatter);
    }

    public static long getNowDateTimeStamp() {
        return Instant.now().toEpochMilli();
    }

    /**
     * 获得当前日期
     *
     * @return
     */
    public static String getNowDate() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDD);
        LocalDateTime localDateTime = LocalDateTime.now();

        return localDateTime.format(formatter);
    }


    /**
     * 根据时间字符串 返回时间类
     *
     * @param dateInput
     * @return
     */
    public static LocalDateTime strToDateTime(String dateInput) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDDHMS);
        LocalDateTime dateTime = LocalDateTime.parse(dateInput, formatter);
        return dateTime;
    }

    /**
     * 根据时间字符串 返回epochmillis 无豪秒 精确到秒
     *
     * @param dateInput
     * @return
     */
    public static long strToDateTimeLong(String dateInput) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDDHMS);
        LocalDateTime dateTime = LocalDateTime.parse(dateInput, formatter);
        Instant it = dateTime.atZone(ZoneId.systemDefault()).toInstant();
        return it.toEpochMilli();
    }

    /**
     * 根据时间字符串和格式 返回epochmillis 无豪秒 精确到秒
     *
     * @param dateInput
     * @param format
     * @return
     */
    public static long strToDateTimeLong(String dateInput, String format) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
        LocalDateTime dateTime = LocalDateTime.parse(dateInput, formatter);
        Instant it = dateTime.atZone(ZoneId.systemDefault()).toInstant();
        return it.toEpochMilli();
    }

    /**
     * 根据时间戳获得字符型时间
     *
     * @param timestamp
     * @return
     */
    public static String timestampToDateTimeStr(long timestamp) {
        Instant it = Instant.ofEpochMilli(timestamp);
        return it.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(YYYYMMDDHMS));

    }

    /**
     * 根据时间戳获得字符型日期
     *
     * @param timestamp
     * @return
     */
    public static String timestampToDateStr(long timestamp) {
        Instant it = Instant.ofEpochMilli(timestamp);
        return it.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(YYYYMMDD));
    }

    /**
     * 根据时间戳获得字符型格式
     *
     * @param timestamp
     * @param format
     * @return
     */
    public static String timestampToDateTimeStr(long timestamp, String format) {
        if (StringUtils.isBlank(format)) {
            return timestampToDateStr(timestamp);
        } else {
            Instant it = Instant.ofEpochMilli(timestamp);
            return it.atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern(format));
        }
    }

    public static String getTimeDiffForHours(String startTime, String endTime) {
        return getTimeDiffForHours(strToDateTimeLong(startTime), strToDateTimeLong(endTime));
    }

    public static String getTimeDiffForHours(long startTime, long endTime) {
        long diff = endTime - startTime;
        return getHours(diff);
    }


    private static String getHours(long time) {
        BigDecimal timeBig = new BigDecimal(time);
        BigDecimal base = new BigDecimal(1000 * 60 * 60);
        BigDecimal result = timeBig.divide(base, 2, BigDecimal.ROUND_DOWN);


        return result.toString();
    }

    public static String getFirstDayOfThisWeek(String... format) {
        String innerFormat = YYYYMMDDHMS;
        if (format.length > 0) {
            innerFormat = format[0];
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(innerFormat);
        int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
        LocalDateTime firstDayOfThisWeek = LocalDate.now().atStartOfDay().minusDays(dayOfWeek - 1);
        return firstDayOfThisWeek.format(formatter);
    }

    public static String getLastDayOfThisWeek(String... format) {
        String innerFormat = YYYYMMDDHMS;
        if (format.length > 0) {
            innerFormat = format[0];
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(innerFormat);
        int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
        LocalDateTime lastDayOfThisWeek = LocalDate.now().atStartOfDay().plusDays(7 - dayOfWeek).plusHours(23).plusMinutes(59).plusSeconds(59);
        return lastDayOfThisWeek.format(formatter);
    }

    public static String getFirstDayOfThisMonth(String... format) {
        String innerFormat = YYYYMMDDHMS;
        if (format.length > 0) {
            innerFormat = format[0];
        }

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(innerFormat);
        LocalDateTime firstDayOfThisMonth = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay();
        return firstDayOfThisMonth.format(formatter);
    }

    public static String getLastDayOfThisMonth(String... format) {
        String innerFormat = YYYYMMDDHMS;
        if (format.length > 0) {
            innerFormat = format[0];
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(innerFormat);
        LocalDateTime lastDayOfThisMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).atStartOfDay().plusHours(23).plusMinutes(59).plusSeconds(59);
        return lastDayOfThisMonth.format(formatter);
    }


    private static final int FIRST_DAY = Calendar.MONDAY;

    public static String[] getWeekdays() {
        return getWeekdays(null);
    }

    public static String[] getWeekdays(Date dataTime) {
        String[] weekDate = new String[7];
        Calendar calendar = Calendar.getInstance();
        if (dataTime != null) {
            calendar.setTime(dataTime);
        }
        setToFirstDay(calendar);
        for (int i = 0; i < 7; i++) {
            weekDate[i] = printDay(calendar);
            calendar.add(Calendar.DATE, 1);
        }
        return weekDate;
    }

    private static void setToFirstDay(Calendar calendar) {
        while (calendar.get(Calendar.DAY_OF_WEEK) != FIRST_DAY) {
            calendar.add(Calendar.DATE, -1);
        }
    }

    private static String printDay(Calendar calendar) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(calendar.getTime());
    }


    public static String[] getMonthDays(String date) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, Integer.parseInt(date.substring(0, 4)));
        calendar.set(Calendar.MONTH, Integer.parseInt(date.substring(5, 7)) - 1);
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        String[] days = new String[maxDay];
        for (int i = 1; i <= maxDay; i++) {
            days[i - 1] = String.valueOf(i);
        }
        return days;
    }

    public static String[] getMonthDays() {
        Calendar calendar = Calendar.getInstance();
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        String[] days = new String[maxDay];
        for (int i = 1; i <= maxDay; i++) {
            days[i - 1] = String.valueOf(i);
        }
        return days;
    }

    /**
     * 取得当月天数
     */
    public static int getCurrentMonthLastDay() {
        Calendar a = Calendar.getInstance();
        a.set(Calendar.DATE, 1);//把日期设置为当月第一天
        a.roll(Calendar.DATE, -1);//日期回滚一天，也就是最后一天
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }

    /**
     * 得到指定月的天数
     */
    public static int getMonthLastDay(int year, int month) {
        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month - 1);
        a.set(Calendar.DATE, 1);//把日期设置为当月第一天
        a.roll(Calendar.DATE, -1);//日期回滚一天，也就是最后一天
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }


}